home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1994 / MacHack 1994.toast / MacHack™ 1987-1994 / MacHack™ '87 / Source ƒ.sea / Source ƒ / emacs source ƒ / BUFFER.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-28  |  15.6 KB  |  503 lines  |  [TEXT/MARC]

  1. /*
  2.  * Buffer management.
  3.  * Some of the functions are internal,
  4.  * and some are actually attached to user
  5.  * keys. Like everyone else, they set hints
  6.  * for the display system.
  7.  */
  8. #include        <stdio.h>
  9. #include    "estruct.h"
  10. #include        "edef.h"
  11.  
  12. /*
  13.  * Attach a buffer to a window. The
  14.  * values of dot and mark come from the buffer
  15.  * if the use count is 0. Otherwise, they come
  16.  * from some other window.
  17.  */
  18. usebuffer(f, n)
  19. {
  20.         register BUFFER *bp;
  21.         register int    s;
  22.         char            bufn[NBUFN];
  23.  
  24.         if ((s=mlreply("Use buffer: ", bufn, NBUFN)) != TRUE)
  25.                 return (s);
  26.         if ((bp=bfind(bufn, TRUE, 0)) == NULL)
  27.                 return (FALSE);
  28.     return(swbuffer(bp));
  29. }
  30.  
  31. nextbuffer(f, n)    /* switch to the next buffer in the buffer list */
  32.  
  33. {
  34.         register BUFFER *bp;
  35.  
  36.     bp = curbp->b_bufp;
  37.     /* cycle through the buffers to find an eligable one */
  38.     while (bp == NULL || bp->b_flag & BFINVS) {
  39.         if (bp == NULL)
  40.             bp = bheadp;
  41.         else
  42.             bp = bp->b_bufp;
  43.     }
  44.     return(swbuffer(bp));
  45. }
  46.  
  47. swbuffer(bp)    /* make buffer BP current */
  48.  
  49. BUFFER *bp;
  50.  
  51. {
  52.         register WINDOW *wp;
  53.  
  54.         if (--curbp->b_nwnd == 0) {             /* Last use.            */
  55.                 curbp->b_dotp  = curwp->w_dotp;
  56.                 curbp->b_doto  = curwp->w_doto;
  57.                 curbp->b_markp = curwp->w_markp;
  58.                 curbp->b_marko = curwp->w_marko;
  59.         }
  60.         curbp = bp;                             /* Switch.              */
  61.     if (curbp->b_active != TRUE) {        /* buffer not active yet*/
  62.         /* read it in and activate it */
  63.         readin(curbp->b_fname, TRUE);
  64.         curbp->b_dotp = lforw(curbp->b_linep);
  65.         curbp->b_doto = 0;
  66.         curbp->b_active = TRUE;
  67.     }
  68.         curwp->w_bufp  = bp;
  69.         curwp->w_linep = bp->b_linep;           /* For macros, ignored. */
  70.         curwp->w_flag |= WFMODE|WFFORCE|WFHARD; /* Quite nasty.         */
  71.         if (bp->b_nwnd++ == 0) {                /* First use.           */
  72.                 curwp->w_dotp  = bp->b_dotp;
  73.                 curwp->w_doto  = bp->b_doto;
  74.                 curwp->w_markp = bp->b_markp;
  75.                 curwp->w_marko = bp->b_marko;
  76.                 return (TRUE);
  77.         }
  78.         wp = wheadp;                            /* Look for old.        */
  79.         while (wp != NULL) {
  80.                 if (wp!=curwp && wp->w_bufp==bp) {
  81.                         curwp->w_dotp  = wp->w_dotp;
  82.                         curwp->w_doto  = wp->w_doto;
  83.                         curwp->w_markp = wp->w_markp;
  84.                         curwp->w_marko = wp->w_marko;
  85.                         break;
  86.                 }
  87.                 wp = wp->w_wndp;
  88.         }
  89.         return (TRUE);
  90. }
  91.  
  92. /*
  93.  * Dispose of a buffer, by name.
  94.  * Ask for the name. Look it up (don't get too
  95.  * upset if it isn't there at all!). Get quite upset
  96.  * if the buffer is being displayed. Clear the buffer (ask
  97.  * if the buffer has been changed). Then free the header
  98.  * line and the buffer header. Bound to "C-X K".
  99.  */
  100. killbuffer(f, n)
  101.  
  102. {
  103.     register BUFFER *bp;
  104.         register int    s;
  105.         char bufn[NBUFN];
  106.  
  107.         if ((s=mlreply("Kill buffer: ", bufn, NBUFN)) != TRUE)
  108.                 return(s);
  109.         if ((bp=bfind(bufn, FALSE, 0)) == NULL) /* Easy if unknown.     */
  110.                 return (TRUE);
  111.     if(bp->b_flag & BFINVS)        /* Deal with special buffers    */
  112.             return (TRUE);        /* by doing nothing.    */
  113.     return(zotbuf(bp));
  114. }
  115.  
  116. zotbuf(bp)    /* kill the buffer pointed to by bp */
  117.  
  118. register BUFFER *bp;
  119.  
  120. {
  121.         register BUFFER *bp1;
  122.         register BUFFER *bp2;
  123.         register int    s;
  124.  
  125.         if (bp->b_nwnd != 0) {                  /* Error if on screen.  */
  126.                 mlwrite("Buffer is being displayed");
  127.                 return (FALSE);
  128.         }
  129.         if ((s=bclear(bp)) != TRUE)             /* Blow text away.      */
  130.                 return (s);
  131.         free((char *) bp->b_linep);             /* Release header line. */
  132.         bp1 = NULL;                             /* Find the header.     */
  133.         bp2 = bheadp;
  134.         while (bp2 != bp) {
  135.                 bp1 = bp2;
  136.                 bp2 = bp2->b_bufp;
  137.         }
  138.         bp2 = bp2->b_bufp;                      /* Next one in chain.   */
  139.         if (bp1 == NULL)                        /* Unlink it.           */
  140.                 bheadp = bp2;
  141.         else
  142.                 bp1->b_bufp = bp2;
  143.         free((char *) bp);                      /* Release buffer block */
  144.         return (TRUE);
  145. }
  146.  
  147. namebuffer(f,n)        /*    Rename the current buffer    */
  148.  
  149. int f, n;        /* default Flag & Numeric arg */
  150.  
  151. {
  152.     register BUFFER *bp;    /* pointer to scan through all buffers */
  153.     char bufn[NBUFN];    /* buffer to hold buffer name */
  154.  
  155.     /* prompt for and get the new buffer name */
  156. ask:    if (mlreply("Change buffer name to: ", bufn, NBUFN) != TRUE)
  157.         return(FALSE);
  158.  
  159.     /* and check for duplicates */
  160.     bp = bheadp;
  161.     while (bp != NULL) {
  162.         if (bp != curbp) {
  163.             /* if the names the same */
  164.             if (strcmp(bufn, bp->b_bname) == 0)
  165.                 goto ask;  /* try again */
  166.         }
  167.         bp = bp->b_bufp;    /* onward */
  168.     }
  169.  
  170.     strcpy(curbp->b_bname, bufn);    /* copy buffer name to structure */
  171.     curwp->w_flag |= WFMODE;    /* make mode line replot */
  172.     mlerase();
  173.     return(TRUE);
  174. }
  175.  
  176. /*
  177.  * List all of the active
  178.  * buffers. First update the special
  179.  * buffer that holds the list. Next make
  180.  * sure at least 1 window is displaying the
  181.  * buffer list, splitting the screen if this
  182.  * is what it takes. Lastly, repaint all of
  183.  * the windows that are displaying the
  184.  * list. Bound to "C-X C-B".
  185.  */
  186. listbuffers(f, n)
  187. {
  188.         register WINDOW *wp;
  189.         register BUFFER *bp;
  190.         register int    s;
  191.  
  192.         if ((s=makelist()) != TRUE)
  193.                 return (s);
  194.         if (blistp->b_nwnd == 0) {              /* Not on screen yet.   */
  195.                 if ((wp=wpopup()) == NULL)
  196.                         return (FALSE);
  197.                 bp = wp->w_bufp;
  198.                 if (--bp->b_nwnd == 0) {
  199.                         bp->b_dotp  = wp->w_dotp;
  200.                         bp->b_doto  = wp->w_doto;
  201.                         bp->b_markp = wp->w_markp;
  202.                         bp->b_marko = wp->w_marko;
  203.                 }
  204.                 wp->w_bufp  = blistp;
  205.                 ++blistp->b_nwnd;
  206.         }
  207.         wp = wheadp;
  208.         while (wp != NULL) {
  209.                 if (wp->w_bufp == blistp) {
  210.                         wp->w_linep = lforw(blistp->b_linep);
  211.                         wp->w_dotp  = lforw(blistp->b_linep);
  212.                         wp->w_doto  = 0;
  213.                         wp->w_markp = NULL;
  214.                         wp->w_marko = 0;
  215.                         wp->w_flag |= WFMODE|WFHARD;
  216.                 }
  217.                 wp = wp->w_wndp;
  218.         }
  219.         return (TRUE);
  220. }
  221.  
  222. /*
  223.  * This routine rebuilds the
  224.  * text in the special secret buffer
  225.  * that holds the buffer list. It is called
  226.  * by the list buffers command. Return TRUE
  227.  * if everything works. Return FALSE if there
  228.  * is an error (if there is no memory).
  229.  */
  230. makelist()
  231. {
  232.         register char   *cp1;
  233.         register char   *cp2;
  234.         register int    c;
  235.         register BUFFER *bp;
  236.         register LINE   *lp;
  237.         register int    s;
  238.     register int    i;
  239.         long    nbytes;        /* # of bytes in current buffer */
  240.         char            b[7+1];
  241.         char            line[128];
  242.  
  243.         blistp->b_flag &= ~BFCHG;               /* Don't complain!      */
  244.         if ((s=bclear(blistp)) != TRUE)         /* Blow old text away   */
  245.                 return (s);
  246.         strcpy(blistp->b_fname, "");
  247.         if (addline("AC MODES       Size Buffer        File") == FALSE
  248.         ||  addline("-- -----       ---- ------        ----") == FALSE)
  249.                 return (FALSE);
  250.         bp = bheadp;                            /* For all buffers      */
  251.  
  252.     /* build line to report global mode settings */
  253.     cp1 = &line[0];
  254.     *cp1++ = ' ';
  255.     *cp1++ = ' ';
  256.     *cp1++ = ' ';
  257.  
  258.     /* output the mode codes */
  259.     for (i = 0; i < NUMMODES; i++)
  260.         if (gmode & (1 << i))
  261.             *cp1++ = modecode[i];
  262.         else
  263.             *cp1++ = '.';
  264.     strcpy(cp1, "         Global Modes");
  265.     if (addline(line) == FALSE)
  266.         return(FALSE);
  267.  
  268.     /* output the list of buffers */
  269.         while (bp != NULL) {
  270.                 if ((bp->b_flag&BFINVS) != 0) { /* Skip magic ones.     */
  271.                         bp = bp->b_bufp;
  272.                         continue;
  273.                 }
  274.                 cp1 = &line[0];                 /* Start at left edge   */
  275.  
  276.         /* output status of ACTIVE flag (has the file been read in? */
  277.                 if (bp->b_active == TRUE)    /* "@" if activated       */
  278.                         *cp1++ = '@';
  279.                 else
  280.                         *cp1++ = ' ';
  281.  
  282.         /* output status of changed flag */
  283.                 if ((bp->b_flag&BFCHG) != 0)    /* "*" if changed       */
  284.                         *cp1++ = '*';
  285.                 else
  286.                         *cp1++ = ' ';
  287.                 *cp1++ = ' ';                   /* Gap.                 */
  288.  
  289.         /* output the mode codes */
  290.         for (i = 0; i < NUMMODES; i++) {
  291.             if (bp->b_mode & (1 << i))
  292.                 *cp1++ = modecode[i];
  293.             else
  294.                 *cp1++ = '.';
  295.         }
  296.                 *cp1++ = ' ';                   /* Gap.                 */
  297.                 nbytes = 0L;                    /* Count bytes in buf.  */
  298.                 lp = lforw(bp->b_linep);
  299.                 while (lp != bp->b_linep) {
  300.                         nbytes += (long)llength(lp)+1L;
  301.                         lp = lforw(lp);
  302.                 }
  303.                 ltoa(b, 7, nbytes);             /* 6 digit buffer size. */
  304.                 cp2 = &b[0];
  305.                 while ((c = *cp2++) != 0)
  306.                         *cp1++ = c;
  307.                 *cp1++ = ' ';                   /* Gap.                 */
  308.                 cp2 = &bp->b_bname[0];          /* Buffer name          */
  309.                 while ((c = *cp2++) != 0)
  310.                         *cp1++ = c;
  311.                 cp2 = &bp->b_fname[0];          /* File name            */
  312.                 if (*cp2 != 0) {
  313.                         while (cp1 < &line[2+1+5+1+6+1+NBUFN])
  314.                                 *cp1++ = ' ';
  315.                         while ((c = *cp2++) != 0) {
  316.                                 if (cp1 < &line[128-1])
  317.                                         *cp1++ = c;
  318.                         }
  319.                 }
  320.                 *cp1 = 0;                       /* Add to the buffer.   */
  321.                 if (addline(line) == FALSE)
  322.                         return (FALSE);
  323.                 bp = bp->b_bufp;
  324.         }
  325.         return (TRUE);                          /* All done             */
  326. }
  327.  
  328. ltoa(buf, width, num)
  329.  
  330. char   buf[];
  331. int    width;
  332. long   num;
  333.  
  334. {
  335.         buf[width] = 0;                         /* End of string.       */
  336.         while (num >= 10) {                     /* Conditional digits.  */
  337.                 buf[--width] = (int)(num%10L) + '0';
  338.                 num /= 10L;
  339.         }
  340.         buf[--width] = (int)num + '0';          /* Always 1 digit.      */
  341.         while (width != 0)                      /* Pad with blanks.     */
  342.                 buf[--width] = ' ';
  343. }
  344.  
  345. /*
  346.  * The argument "text" points to
  347.  * a string. Append this line to the
  348.  * buffer list buffer. Handcraft the EOL
  349.  * on the end. Return TRUE if it worked and
  350.  * FALSE if you ran out of room.
  351.  */
  352. addline(text)
  353. char    *text;
  354. {
  355.         register LINE   *lp;
  356.         register int    i;
  357.         register int    ntext;
  358.  
  359.         ntext = strlen(text);
  360.         if ((lp=lalloc(ntext)) == NULL)
  361.                 return (FALSE);
  362.         for (i=0; i<ntext; ++i)
  363.                 lputc(lp, i, text[i]);
  364.         blistp->b_linep->l_bp->l_fp = lp;       /* Hook onto the end    */
  365.         lp->l_bp = blistp->b_linep->l_bp;
  366.         blistp->b_linep->l_bp = lp;
  367.         lp->l_fp = blistp->b_linep;
  368.         if (blistp->b_dotp == blistp->b_linep)  /* If "." is at the end */
  369.                 blistp->b_dotp = lp;            /* move it to new line  */
  370.         return (TRUE);
  371. }
  372.  
  373. /*
  374.  * Look through the list of
  375.  * buffers. Return TRUE if there
  376.  * are any changed buffers. Buffers
  377.  * that hold magic internal stuff are
  378.  * not considered; who cares if the
  379.  * list of buffer names is hacked.
  380.  * Return FALSE if no buffers
  381.  * have been changed.
  382.  */
  383. anycb()
  384. {
  385.         register BUFFER *bp;
  386.  
  387.         bp = bheadp;
  388.         while (bp != NULL) {
  389.                 if ((bp->b_flag&BFINVS)==0 && (bp->b_flag&BFCHG)!=0)
  390.                         return (TRUE);
  391.                 bp = bp->b_bufp;
  392.         }
  393.         return (FALSE);
  394. }
  395.  
  396. /*
  397.  * Find a buffer, by name. Return a pointer
  398.  * to the BUFFER structure associated with it.
  399.  * If the buffer is not found
  400.  * and the "cflag" is TRUE, create it. The "bflag" is
  401.  * the settings for the flags in in buffer.
  402.  */
  403. BUFFER  *
  404. bfind(bname, cflag, bflag)
  405. register char   *bname;
  406. {
  407.         register BUFFER *bp;
  408.     register BUFFER *sb;    /* buffer to insert after */
  409.         register LINE   *lp;
  410.     char *malloc();
  411.  
  412.         bp = bheadp;
  413.         while (bp != NULL) {
  414.                 if (strcmp(bname, bp->b_bname) == 0)
  415.                         return (bp);
  416.                 bp = bp->b_bufp;
  417.         }
  418.         if (cflag != FALSE) {
  419.                 if ((bp=(BUFFER *)malloc(sizeof(BUFFER))) == NULL)
  420.                         return (NULL);
  421.                 if ((lp=lalloc(0)) == NULL) {
  422.                         free((char *) bp);
  423.                         return (NULL);
  424.                 }
  425.         /* find the place in the list to insert this buffer */
  426.         if (bheadp == NULL || strcmp(bheadp->b_bname, bname) > 0) {
  427.             /* insert at the beginning */
  428.                     bp->b_bufp = bheadp;
  429.                     bheadp = bp;
  430.             } else {
  431.             sb = bheadp;
  432.             while (sb->b_bufp != NULL) {
  433.                 if (strcmp(sb->b_bufp->b_bname, bname) > 0)
  434.                     break;
  435.                 sb = sb->b_bufp;
  436.             }
  437.  
  438.             /* and insert it */
  439.                    bp->b_bufp = sb->b_bufp;
  440.                 sb->b_bufp = bp;
  441.                }
  442.  
  443.         /* and set up the other buffer fields */
  444.         bp->b_active = TRUE;
  445.                 bp->b_dotp  = lp;
  446.                 bp->b_doto  = 0;
  447.                 bp->b_markp = NULL;
  448.                 bp->b_marko = 0;
  449.                 bp->b_flag  = bflag;
  450.         bp->b_mode  = gmode;
  451.                 bp->b_nwnd  = 0;
  452.                 bp->b_linep = lp;
  453.                 strcpy(bp->b_fname, "");
  454.                 strcpy(bp->b_bname, bname);
  455. #if    CRYPT
  456.         bp->b_key[0] = 0;
  457. #endif
  458.                 lp->l_fp = lp;
  459.                 lp->l_bp = lp;
  460.         }
  461.         return (bp);
  462. }
  463.  
  464. /*
  465.  * This routine blows away all of the text
  466.  * in a buffer. If the buffer is marked as changed
  467.  * then we ask if it is ok to blow it away; this is
  468.  * to save the user the grief of losing text. The
  469.  * window chain is nearly always wrong if this gets
  470.  * called; the caller must arrange for the updates
  471.  * that are required. Return TRUE if everything
  472.  * looks good.
  473.  */
  474. bclear(bp)
  475. register BUFFER *bp;
  476. {
  477.         register LINE   *lp;
  478.         register int    s;
  479.  
  480.         if ((bp->b_flag&BFINVS) == 0            /* Not scratch buffer.  */
  481.         && (bp->b_flag&BFCHG) != 0              /* Something changed    */
  482.         && (s=mlyesno("Discard changes")) != TRUE)
  483.                 return (s);
  484.         bp->b_flag  &= ~BFCHG;                  /* Not changed          */
  485.         while ((lp=lforw(bp->b_linep)) != bp->b_linep)
  486.                 lfree(lp);
  487.         bp->b_dotp  = bp->b_linep;              /* Fix "."              */
  488.         bp->b_doto  = 0;
  489.         bp->b_markp = NULL;                     /* Invalidate "mark"    */
  490.         bp->b_marko = 0;
  491.         return (TRUE);
  492. }
  493.  
  494. unmark(f, n)    /* unmark the current buffers change flag */
  495.  
  496. int f, n;    /* unused command arguments */
  497.  
  498. {
  499.     curbp->b_flag &= ~BFCHG;
  500.     curwp->w_flag |= WFMODE;
  501.     return(TRUE);
  502. }
  503.